package net.amsoft.iservice.util;

import java.util.ArrayList;
import java.util.InvalidPropertiesFormatException;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RedirectorConfig
{
	private int hashValue = 0;
	public static final String PATH_REGEX = "/(\\(\\+\\w+\\))\\*(.*)(\\(\\$v\\*[\\d|.]+\\))/(\\(!.*\\))";
	private static final Pattern PATH_PATTERN;
	public static final String SERVICE_CONTACT = "(+contact)";
	public static final String SERVICE_AUTHN = "(+authn)";
	public static final String SERVICE_FORWARDING = "(+forwarding)";

	/*
	 * TODO: this assumes that all the services have the same versions. I at any
	 * need to support different versions of different services the supported
	 * versions and services have to be coupled
	 */
	public static final String VERSION_ONE_ZERO = "($v*1.0)";
	public static final String PROTOCOL_SAML = "(+saml)";
	private String service;
	private String version;
	private String networkINumber;
	private String protocol;
	public static ArrayList SUPPORTED_PROTOCOLS = new ArrayList();
	public static ArrayList SUPPORTED_SERVICES = new ArrayList();
	public static ArrayList SUPPORTED_VERSIONS = new ArrayList();

	static
	{
		SUPPORTED_PROTOCOLS.add(PROTOCOL_SAML);
		SUPPORTED_SERVICES.add(SERVICE_AUTHN);
		SUPPORTED_SERVICES.add(SERVICE_CONTACT);
		SUPPORTED_SERVICES.add(SERVICE_FORWARDING);

		SUPPORTED_VERSIONS.add(VERSION_ONE_ZERO);

		PATH_PATTERN = Pattern.compile(PATH_REGEX);
	}

	public RedirectorConfig(String service, String version,
			String networkINumber, String protocol)
	{
		super();
		this.service = service;
		this.version = version;
		this.networkINumber = networkINumber;
		this.protocol = protocol;

	}

	public RedirectorConfig()
	{
		super();
		this.service = null;
		this.version = null;
		this.networkINumber = null;
		this.protocol = null;
	}

	/**
	 * 
	 * @param propFileValue:
	 *            Format is: (+<SERVICE>),($v*<VERSION>),(!!<NETWORK
	 *            i-NUMBER>), (+<PROTOCOL>)
	 * @throws InvalidPropertiesFormatException
	 */
	public RedirectorConfig(String propFileValue)
			throws InvalidPropertiesFormatException
	{
		StringTokenizer tokenizer = new StringTokenizer(propFileValue, ",");
		int noOfTokens = tokenizer.countTokens();
		if (noOfTokens != 3)
		{
			throw new InvalidPropertiesFormatException(
					"Too many or too few comma delimited values");
		}
		this.setService(tokenizer.nextToken());
		this.setVersion(tokenizer.nextToken());
		this.setNetworkINumber(tokenizer.nextToken());
	}

	public void populateFromPath(String path)
	{
		Matcher matcher = PATH_PATTERN.matcher(path);
		if (matcher.matches())
		{
			this.service = matcher.group(1);
			this.protocol = matcher.group(2).replace("*", "");
			this.version = matcher.group(3);
			this.networkINumber = matcher.group(4);
		}
	}

	public String getNetworkINumber()
	{
		return networkINumber;
	}

	public void setNetworkINumber(String networkINumber)
	{
		this.networkINumber = networkINumber;
	}

	public String getService()
	{
		return service;
	}

	public void setService(String service)
	{
		this.service = service;
	}

	public String getVersion()
	{
		return version;
	}

	public void setVersion(String version)
	{
		this.version = version;
	}

	public int hashCode()
	{
		if (this.hashValue == 0)
		{
			int result = 17;
			int val = ((this.service == null) | (this.version == null) | (this.networkINumber == null))
					? 0
					: this.service.hashCode() + this.version.hashCode()
							+ this.networkINumber.hashCode();
			result = result * 37 + val;
			this.hashValue = result;
		}
		return this.hashValue;
	}

	public boolean equals(Object rhs)
	{
		if (rhs == null)
			return false;
		if (!(rhs instanceof RedirectorConfig))
			return false;
		RedirectorConfig that = (RedirectorConfig) rhs;
		if (this.hashCode() == that.hashCode())
		{
			return true;
		}
		return false;
	}

	public String getProtocol()
	{
		return protocol;
	}

	public void setProtocol(String protocol)
	{
		this.protocol = protocol;
	}

}
